
package org.okkam.refine.commands;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

//import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
//import org.apache.commons.math.stat.descriptive.rank.Median;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;

import com.google.refine.commands.Command;
import com.google.refine.ProjectManager;
import com.google.refine.model.Project;
import com.google.refine.model.ColumnModel;
import com.google.refine.model.Column;
import com.google.refine.model.Row;
import com.google.refine.browsing.Engine;
import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RowVisitor;
import com.google.refine.util.ParsingUtilities;
/**
 * 
 * Validates codice Fiscale in a column.
 *
 */
public class ValidateCodiceFiscaleCommand extends Command {

    protected RowVisitor createRowVisitor(Project project, int cellIndex, List values)
            throws Exception {
        return new RowVisitor() {

            int cellIndex;
            List values;

            public RowVisitor init(int cellIndex, List<Float> values) {
                this.cellIndex = cellIndex;
                this.values = values;
                return this;
            }

            @Override
            public void start(Project project) {
                // nothing to do
            }

            @Override
            public void end(Project project) {
                // nothing to do
            }

            public boolean visit(Project project, int rowIndex, Row row) {
                try {
                    String val = (String) row.getCellValue(this.cellIndex);
                    this.values.add(val);
                } catch (Exception e) {
                }

                return false;
            }
        }.init(cellIndex, values);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    };

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            ProjectManager.singleton.setBusy(true);
            Project project = getProject(request);
            ColumnModel columnModel = project.columnModel;
            Column column = columnModel.getColumnByName(request.getParameter("column_name"));
            int cellIndex = column.getCellIndex();

            List values = new ArrayList();// list of okkam IDs to be deleted

            Engine engine = new Engine(project);
            JSONObject engineConfig = null;

            try {
                engineConfig = ParsingUtilities.evaluateJsonStringToObject(request.getParameter("engine"));
            } catch (JSONException e) {
                // ignore
            }

            engine.initializeFromJSON(engineConfig);

            FilteredRows filteredRows = engine.getAllFilteredRows();
            filteredRows.accept(project, createRowVisitor(project, cellIndex, values));

            Iterator<String> CF = values.iterator();
            Set<String> invalidCF = new HashSet<String>();

            int rowIndexes = 0;

            while (CF.hasNext()) {
                try {
                    rowIndexes++;
                    String CodiceFiscale = CF.next();
                    if (!controllaCF(CodiceFiscale) && !"".equals(CodiceFiscale)) {
                        invalidCF.add(CodiceFiscale);
                    }

                } catch (Exception e) {
                    System.out.println( e);
                }
            }

            JSONWriter writer = new JSONWriter(response.getWriter());
            Iterator<String> invalidCFit = invalidCF.iterator();

            writer.object();
            int index = 0;
            ;
            String invalidCFs = "";
            while (invalidCFit.hasNext()) {
                invalidCFs += invalidCFit.next() + "<br>";

            }
            System.out.println(invalidCFs);
            writer.key("CF");
            writer.value(invalidCFs);

            writer.endObject();

        } catch (Exception e) {
            respondException(response, e);
        } finally {
            ProjectManager.singleton.setBusy(false);
        }
    };

    public boolean controllaCF(String cf) {
        int i, s, c;
        String cf2;
        int setdisp[] = { 1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23 };
        if (cf.length() == 0) return false;
        if (cf.length() != 16) return false;
        cf2 = cf.toUpperCase();
        for (i = 0; i < 16; i++) {
            c = cf2.charAt(i);
            if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'Z')) return false;
        }
        s = 0;
        for (i = 1; i <= 13; i += 2) {
            c = cf2.charAt(i);
            if (c >= '0' && c <= '9')
                s = s + c - '0';
            else
                s = s + c - 'A';
        }
        for (i = 0; i <= 14; i += 2) {
            c = cf2.charAt(i);
            if (c >= '0' && c <= '9') c = c - '0' + 'A';
            s = s + setdisp[c - 'A'];
        }
        if (s % 26 + 'A' != cf2.charAt(15)) return false;
        return true;
    }

}
